package br.unifor.cct.mia.runner;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;

import weka.gui.explorer.ClassifierPanel;
import br.unifor.cct.mia.coevolution.InvalidTypeException;
import br.unifor.cct.mia.dataenhancement.Database;
import br.unifor.cct.mia.dataenhancement.GenotypeConverter;
import br.unifor.cct.mia.dataenhancement.Structure;
import br.unifor.cct.mia.evaluate.Evaluate;
import br.unifor.cct.mia.evaluate.classification.WekaClassification;
import br.unifor.cct.mia.evolutionary.Genotype;
import br.unifor.cct.mia.evolutionary.SpeciesConstants;
import br.unifor.cct.mia.ga.GaFSIS;
import br.unifor.cct.mia.util.Configurations;
import br.unifor.cct.mia.util.LoadFile;

/**
 * Feature e Instance Selection Simples no mesmo gene
 * @author Pedro
 *
 */
public class FeatureInstanceSelection {
	
	public static String BASE_NAME = "car";
	public static String DATASET_STRUCTURE = "./data/"+BASE_NAME+"_estrutura.txt";
	public static String DATASET_DATA = "./dataPart/"+BASE_NAME+"_TRAIN_data.txt";
	public static String DATASET_TESTE = "./dataPart/"+BASE_NAME+"_TEST_data.txt";
	public static String RESULT_SERIAL_FILE = "./results/result_"+BASE_NAME+"_FSIS.ser";

	public static Integer learnerType = Evaluate.J48;
	
	public static void main(String[] a) {	
    
		Structure st = LoadFile.loadStructure(DATASET_STRUCTURE);
    	Database db = LoadFile.loadDatabase(DATASET_DATA);
		System.out.println("Arquivos carregados com sucesso");		
		
		try {
			GaFSIS ga = new GaFSIS(db,st,null);
            Thread t = new Thread(ga);
            
            System.out.println("### INIT TIME: "+new Date());
            t.start();
        	t.join();
        	System.out.println("### END TIME: "+new Date());        	
        	
        	/*ObjectOutput out = new ObjectOutputStream(new FileOutputStream(RESULT_SERIAL_FILE));
		    out.writeObject(ga.population[ga.indexBestWorst[0]]);
		    out.close();*/
		    
		    boolean testSetOnly = true;
		    WekaClassification classifier = new WekaClassification(learnerType,null);	
		    //classifier.setTestType(ClassifierPanel.SUPPLIED_TEST_SET);	    
		    GenotypeConverter converter = new GenotypeConverter();
		    
        	/** Calcula o fitness utilizando dataset de teste */        	        	
		    //Deve treinar com a base de dados de treinamento
        	Genotype bestGenotype = (Genotype)ga.population[ga.indexBestWorst[0]];		  
        	//Arquivo de treinamento
        	File trainFile = converter.convert(bestGenotype,SpeciesConstants.FEATURE_INSTANCE_SELECTION,"temp/resultFSISTrain.txt",st,db,null,null);	
        	double parcialResult = classifier.evaluate(trainFile,trainFile);
        	//Arquivo de Teste
        	File testFile = null;
        	//Cria um gen para fazer o instance selection nos dados de treinamento
        	Configurations config = new Configurations();
			config.setNvars(st.size()-1);				
			double[] auxGens = new double[config.getNvars()];
			System.arraycopy(bestGenotype.getGene(),0,auxGens,0,config.getNvars());			
			Genotype fsGen = new Genotype(config);			
			fsGen.setGene(auxGens);
			//Gera o arquivo de teste
        	if ( testSetOnly ) {
        		/** Daqui para baixo faz apenas 20% **/
        		Database dbTeste = LoadFile.loadDatabase(DATASET_TESTE);
        		testFile = converter.convert(fsGen,SpeciesConstants.FEATURE_SELECTION,"resultFSISTeste.txt",st,dbTeste,null,null);
        	}
        	else {
        		/** Daqui para baixo faz 80% + 20% **/
	        	testFile = converter.convert(bestGenotype,SpeciesConstants.FEATURE_INSTANCE_SELECTION,"resultFSISTeste.txt",st,db,null,null);	        	
	        	//Adiciona as linhas no arquivo de teste
	        	converter.addTestData(fsGen,SpeciesConstants.FEATURE_SELECTION,st,DATASET_TESTE,testFile);
        	}
        	//Roda o classificador    		    
		    double finalResult = classifier.evaluate(trainFile,testFile);
		    
		    System.out.println("\n\n##################################");
		    System.out.println("######### Resultado Geral ########");
		    System.out.println("Fitness Best Ga: "+parcialResult);
		    System.out.println("Fitness Best Ga + Teste: "+finalResult);
		    System.out.println("##################################");
		    
        	System.out.println("Processo finalizado com sucesso!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InvalidTypeException e) {
			e.printStackTrace();
		}
	}
}
